/* ** por compatibilidad se omiten tildes **
================================================================================
 TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
================================================================================
*/

#include "game.h"
#include "screen.h"
#include "sched.h"
#include "tss.h"
#include "mmu.h"
#include "i386.h"

static int posicion_jugadores_rojos[CANT_ZOMBIS][2];
static int posicion_jugadores_azules[CANT_ZOMBIS][2];
static int tipo_zombi_rojos[CANT_ZOMBIS];
static int tipo_zombi_azules[CANT_ZOMBIS];
static int posicion_zombi_a_lanzar_rojo;
static int posicion_zombi_a_lanzar_azul;
static int tipo_zombi_rojo = 1;
static int tipo_zombi_azul = 1;
static int tiempo_prudencial = TIEMPO_PRUDENCIAL;
static int juego_terminado = 0;
static int modo_debug = 0;
static int mostrando_excepcion = 0;

char * obtener_nombre_tipo_ampliado(unsigned int tipo) {
	switch (tipo) {
		case 0:
		   return "Zombie B  Guerrero";
		case 1:
		   return "Zombie B  Mago    ";
		case 2:
		   return "Zombie B  Clerigo ";
	}

	return "";
}


void setear_modo_debug() {
	if (modo_debug == 1) {
		if (mostrando_excepcion == 1) {
			restaurar_screen();
			mostrando_excepcion = 0;
		} else {
		
			print("          ", 0, 0, 0x0F);
			modo_debug = 0;
		}
	} else {
		modo_debug = 1;
		print("modo debug", 0, 0, 0x0F);
	}
}

unsigned int esta_mostrando_excepcion() {
	return mostrando_excepcion;
}
void imprimir_contexto_excepcion(char * mensaje_excepcion, unsigned int length) {
	if (modo_debug == 0 || mostrando_excepcion == 1)
		return;

	if (es_actual_rojo()) {
		imprimir_zombi_destruido(
					posicion_jugadores_rojos[obtener_zombi_actual_rojo()][0], 
					posicion_jugadores_rojos[obtener_zombi_actual_rojo()][1], 
					0); // pinto el zombie destruido en su posición
	} else {
		imprimir_zombi_destruido(
					posicion_jugadores_azules[obtener_zombi_actual_azul()][0], 
					posicion_jugadores_azules[obtener_zombi_actual_azul()][1], 
					1); // pinto el zombie destruido en su posición

	}

	mostrando_excepcion = 1;
	if (es_actual_rojo()) {

		imprimir_contexto_game(obtener_zombi_actual_rojo(), 0,  obtener_nombre_tipo_ampliado(tipo_zombi_rojos[obtener_zombi_actual_rojo()]),
					mensaje_excepcion, length);
	} else {

		imprimir_contexto_game(obtener_zombi_actual_azul(), 1,  obtener_nombre_tipo_ampliado(tipo_zombi_azules[obtener_zombi_actual_azul()]),
				mensaje_excepcion, length);
	}
}	
void disable_modo_debug() {
	modo_debug = 0;
}
 
unsigned int es_juego_terminado() {
	return juego_terminado;
}
void terminar_juego() {
     print("juego terminado", 0, 0, 0x0F);
     juego_terminado = 1;
}

unsigned int dame_tiempo_prudencial() {
	return tiempo_prudencial;
}
void reducir_tiempo_prudencial() {
	tiempo_prudencial--;
} 
void resetear_tiempo_prudencial() {
	tiempo_prudencial = TIEMPO_PRUDENCIAL; 
}


char * obtener_tipo_zombie_rojo_str(int tipo) {
	switch (tipo) {
		case 0:
		    return TIPO_GUERRERO;
		case 1:
		    return TIPO_MAGO;
		case 2:
		    return TIPO_CLERIGO;
	}
	return TIPO_MAGO;
}

char * obtener_tipo_zombie_azul_str(int tipo) {
	switch (tipo) {
		case 0:
		    return TIPO_GUERRERO;
		case 1:
		    return TIPO_MAGO;
		case 2:
		    return TIPO_CLERIGO;
	}
	return TIPO_MAGO;
}


void game_jugador_mover(unsigned int jugador, unsigned int value) {
	if (mostrando_excepcion == 1)
		return;

	resetear_tiempo_prudencial();
	if (jugador == 0) {
		borrar_posicion_zombi_jugador_rojo(posicion_zombi_a_lanzar_rojo);
		if (value == 0) {
			posicion_zombi_a_lanzar_rojo++;
			if (posicion_zombi_a_lanzar_rojo == 44)
				posicion_zombi_a_lanzar_rojo = 0;
		} else {
			posicion_zombi_a_lanzar_rojo--;
			if (posicion_zombi_a_lanzar_rojo == -1)
				posicion_zombi_a_lanzar_rojo = 43;

		}
		pintar_posicion_zombi_jugador_rojo(posicion_zombi_a_lanzar_rojo,  obtener_tipo_zombie_rojo_str(tipo_zombi_rojo));

	} else {
		borrar_posicion_zombi_jugador_azul(posicion_zombi_a_lanzar_azul);
		if (value == 0) {
			posicion_zombi_a_lanzar_azul++;
			if (posicion_zombi_a_lanzar_azul == 44)
				posicion_zombi_a_lanzar_azul = 0;
		} else {
			posicion_zombi_a_lanzar_azul--;
			if (posicion_zombi_a_lanzar_azul == -1)
				posicion_zombi_a_lanzar_azul = 43;

		}
		pintar_posicion_zombi_jugador_azul(posicion_zombi_a_lanzar_azul, obtener_tipo_zombie_azul_str(tipo_zombi_azul)); 
	}


}


void game_lanzar_zombi(unsigned int jugador) {
	if (mostrando_excepcion == 1)
		return;

	if (jugador == 0) {


		if (dame_restantes_rojo() == 0) {
			return;
		} else {
			reducir_restantes_rojo();
		}
		
		int zombi_actual = obtener_slot_libre_rojo();
		
		if (zombi_actual == CANT_ZOMBIS)
			return;
		posicion_jugadores_rojos[zombi_actual][0] = 1;
		posicion_jugadores_rojos[zombi_actual][1] = posicion_zombi_a_lanzar_rojo + 1;			
		tipo_zombi_rojos[zombi_actual] = tipo_zombi_rojo;
		configurar_tarea_zombi_rojo(zombi_actual);
		pintar_zombie_mapa_rojo(posicion_jugadores_rojos[zombi_actual][0], 
					posicion_jugadores_rojos[zombi_actual][1], 
					obtener_tipo_zombie_rojo_str(tipo_zombi_rojos[zombi_actual]));
		enable_hay_zombis_activos_rojos();

	} else {

		if (dame_restantes_azul() == 0) {
			return;
		} else {
			reducir_restantes_azul();
		}

		int zombi_actual = obtener_slot_libre_azul();
		
		if (zombi_actual == CANT_ZOMBIS)
			return;


		posicion_jugadores_azules[zombi_actual][0] = 78;
		posicion_jugadores_azules[zombi_actual][1] = posicion_zombi_a_lanzar_azul + 1;
		tipo_zombi_azules[zombi_actual] = tipo_zombi_azul;
		configurar_tarea_zombi_azul(zombi_actual);
		pintar_zombie_mapa_azul(posicion_jugadores_azules[zombi_actual][0], 
					posicion_jugadores_azules[zombi_actual][1], 
					obtener_tipo_zombie_azul_str(tipo_zombi_azules[zombi_actual]));
		enable_hay_zombis_activos_azules();

	}	
}

/**
*  game_desalojar_zombie_actual()
*  
*  Se encarga de desalojar la tarea actual.
*  Se llama cuando arroja una excepción.
*/
void game_desalojar_zombie_actual() {	

	// verifico si es rojo o azul el zombi que se
	// está ejecutando
	if (es_actual_rojo()) {
		int zombi_actual = obtener_zombi_actual_rojo(); // obtengo el zombi que se está ejecutando
		imprimir_zombi_destruido(
				posicion_jugadores_rojos[zombi_actual][0], 
				posicion_jugadores_rojos[zombi_actual][1], 
				0); // pinto el zombie destruido en su posición
		desalojar_zombie_rojo(zombi_actual); //  lo desalojo

 	} else { // lo mismo para rojo
		int zombi_actual = obtener_zombi_actual_azul();
		imprimir_zombi_destruido(posicion_jugadores_azules[zombi_actual][0], posicion_jugadores_azules[zombi_actual][1], 1);
		desalojar_zombie_azul(zombi_actual);

	}

}
void game_move_current_zombi(int dir) {

	if (mostrando_excepcion == 1)
		return;
	 
	if (dir == 0) {
		if (es_actual_rojo() == 1) {
			int zombi_actual = obtener_zombi_actual_rojo();
			pintar_recorrido(posicion_jugadores_rojos[zombi_actual][0], 
					posicion_jugadores_rojos[zombi_actual][1]);
			
			posicion_jugadores_rojos[zombi_actual][1] += 1;		


			if (posicion_jugadores_rojos[zombi_actual][1] == 45) {
				posicion_jugadores_rojos[zombi_actual][1] = 1;
			}
			pintar_zombie_mapa_rojo(posicion_jugadores_rojos[zombi_actual][0], 
						posicion_jugadores_rojos[zombi_actual][1], 
						obtener_tipo_zombie_rojo_str(tipo_zombi_rojos[zombi_actual]));
			

			copiar_pegar(zombi_actual, 0);
			avanzar_reloj_zombie_rojo(zombi_actual);
			imprimir_reloj_zombie_rojo(zombi_actual);

		} else {
			int zombi_actual = obtener_zombi_actual_azul();
			pintar_recorrido(posicion_jugadores_azules[zombi_actual][0], 
					posicion_jugadores_azules[zombi_actual][1]);
			

			if (posicion_jugadores_azules[zombi_actual][1] == 1) {
				posicion_jugadores_azules[zombi_actual][1] = 45;
			}

			posicion_jugadores_azules[zombi_actual][1] -= 1;

			pintar_zombie_mapa_azul(posicion_jugadores_azules[zombi_actual][0], 
						posicion_jugadores_azules[zombi_actual][1], 
						obtener_tipo_zombie_azul_str(tipo_zombi_azules[zombi_actual]));
			copiar_pegar(zombi_actual, 1);
			avanzar_reloj_zombie_azul(zombi_actual);
			imprimir_reloj_zombie_azul(zombi_actual);

		}
	}

	if (dir == 1) {
		if (es_actual_rojo() == 1) {
			int zombi_actual = obtener_zombi_actual_rojo();
			pintar_recorrido(posicion_jugadores_rojos[zombi_actual][0], 
					posicion_jugadores_rojos[zombi_actual][1]);
			
			posicion_jugadores_rojos[zombi_actual][1] -= 1;

			if (posicion_jugadores_rojos[zombi_actual][1] == 0) {
				posicion_jugadores_rojos[zombi_actual][1] = 44;
			}

			pintar_zombie_mapa_rojo(posicion_jugadores_rojos[zombi_actual][0], 
						posicion_jugadores_rojos[zombi_actual][1], 
						obtener_tipo_zombie_rojo_str(tipo_zombi_rojos[zombi_actual]));
			copiar_pegar(zombi_actual, 0);
			avanzar_reloj_zombie_rojo(zombi_actual);
			imprimir_reloj_zombie_rojo(zombi_actual);

			
		} else {
			int zombi_actual = obtener_zombi_actual_azul();
			pintar_recorrido(posicion_jugadores_azules[zombi_actual][0], 
					posicion_jugadores_azules[zombi_actual][1]);
			
			posicion_jugadores_azules[zombi_actual][1] += 1;

			if (posicion_jugadores_azules[zombi_actual][1] == 45) {
				posicion_jugadores_azules[zombi_actual][1] = 1;
			}

			pintar_zombie_mapa_azul(posicion_jugadores_azules[zombi_actual][0], 
						posicion_jugadores_azules[zombi_actual][1], 
						obtener_tipo_zombie_azul_str(tipo_zombi_azules[zombi_actual]));
			copiar_pegar(zombi_actual, 1);
			avanzar_reloj_zombie_azul(zombi_actual);
			imprimir_reloj_zombie_azul(zombi_actual);

		}
	}

	if (dir == 2) {
		if (es_actual_rojo() == 1) {
			int zombi_actual = obtener_zombi_actual_rojo();
			pintar_recorrido(posicion_jugadores_rojos[zombi_actual][0], 
					posicion_jugadores_rojos[zombi_actual][1]);
			
			posicion_jugadores_rojos[zombi_actual][0] -= 1;
			pintar_zombie_mapa_rojo(posicion_jugadores_rojos[zombi_actual][0], 
						posicion_jugadores_rojos[zombi_actual][1], 
						obtener_tipo_zombie_rojo_str(tipo_zombi_rojos[zombi_actual]));

			copiar_pegar(zombi_actual, 0);
			avanzar_reloj_zombie_rojo(zombi_actual);
			imprimir_reloj_zombie_rojo(zombi_actual);

			
		} else {
			int zombi_actual = obtener_zombi_actual_azul();
			pintar_recorrido(posicion_jugadores_azules[zombi_actual][0], 
					posicion_jugadores_azules[zombi_actual][1]);
			
			posicion_jugadores_azules[zombi_actual][0] += 1;

			pintar_zombie_mapa_azul(posicion_jugadores_azules[zombi_actual][0], 
						posicion_jugadores_azules[zombi_actual][1], 
						obtener_tipo_zombie_azul_str(tipo_zombi_azules[zombi_actual]));
			copiar_pegar(zombi_actual, 1);
			avanzar_reloj_zombie_azul(zombi_actual);
			imprimir_reloj_zombie_azul(zombi_actual);

		}
	}				

	if (dir == 3) {
		if (es_actual_rojo() == 1) {
        		int zombi_actual = obtener_zombi_actual_rojo();

			pintar_recorrido(posicion_jugadores_rojos[zombi_actual][0], 
					posicion_jugadores_rojos[zombi_actual][1]);
			
			posicion_jugadores_rojos[zombi_actual][0] += 1;

			pintar_zombie_mapa_rojo(posicion_jugadores_rojos[zombi_actual][0], 
						posicion_jugadores_rojos[zombi_actual][1], 
						obtener_tipo_zombie_rojo_str(tipo_zombi_rojos[zombi_actual]));
			copiar_pegar(zombi_actual, 0);
			avanzar_reloj_zombie_rojo(zombi_actual);
			imprimir_reloj_zombie_rojo(zombi_actual);
			
		} else {
        		int zombi_actual = obtener_zombi_actual_azul();
			pintar_recorrido(posicion_jugadores_azules[zombi_actual][0], 
					posicion_jugadores_azules[zombi_actual][1]);
			
			posicion_jugadores_azules[zombi_actual][0] -= 1;
			pintar_zombie_mapa_azul(posicion_jugadores_azules[zombi_actual][0], 
						posicion_jugadores_azules[zombi_actual][1], 
						obtener_tipo_zombie_azul_str(tipo_zombi_azules[zombi_actual]));
			copiar_pegar(zombi_actual, 1);
			avanzar_reloj_zombie_azul(zombi_actual);
			imprimir_reloj_zombie_azul(zombi_actual);

		}
	}		

	if (es_actual_rojo() == 1)  {
		int zombi_actual = obtener_zombi_actual_rojo();
		if (posicion_jugadores_rojos[zombi_actual][0] == 1) {
			desalojar_zombie_rojo(zombi_actual);
			imprimir_zombi_destruido(1, posicion_jugadores_rojos[zombi_actual][1], 0);
			aumentar_puntos_azul();
		}

		if (posicion_jugadores_rojos[zombi_actual][0] == 78) {
			desalojar_zombie_rojo(zombi_actual);
			imprimir_zombi_destruido(78, posicion_jugadores_rojos[zombi_actual][1], 0);
			aumentar_puntos_rojo();
		}

	} else {
		int zombi_actual = obtener_zombi_actual_azul();
		if (posicion_jugadores_azules[zombi_actual][0] == 1) {
			desalojar_zombie_azul(zombi_actual);
			imprimir_zombi_destruido(1, posicion_jugadores_azules[zombi_actual][1], 1);	
			aumentar_puntos_azul();
		}


		if (posicion_jugadores_azules[zombi_actual][0] == 78) {
			desalojar_zombie_azul(zombi_actual);
			imprimir_zombi_destruido(78, posicion_jugadores_azules[zombi_actual][1], 1);
			aumentar_puntos_rojo();
		}

	}
}

void game_cambiar_tipo_zombie(int color, int direccion) {
	if (mostrando_excepcion == 1)
		return;

	if (color == 0) {
		if (direccion == 0) {
			tipo_zombi_rojo++;
			if (tipo_zombi_rojo == 3) {
			  tipo_zombi_rojo = 0;
			}
		} else {
			tipo_zombi_rojo--;
			if (tipo_zombi_rojo == -1) {
			  tipo_zombi_rojo = 2;
			}


		}
	pintar_posicion_zombi_jugador_rojo(posicion_zombi_a_lanzar_rojo, obtener_tipo_zombie_rojo_str(tipo_zombi_rojo));

	} else {
		if (direccion == 0) {
			tipo_zombi_azul++;
			if (tipo_zombi_azul == 3) {
			  tipo_zombi_azul = 0;
			}

		} else {
			tipo_zombi_azul--;
			if (tipo_zombi_azul == -1) {
			  tipo_zombi_azul = 2;
			}

		}
	pintar_posicion_zombi_jugador_azul(posicion_zombi_a_lanzar_azul, obtener_tipo_zombie_azul_str(tipo_zombi_azul));
	
	}
}
void game_inicializar() {
	// inicializo la posicion inicial de los zombies (están fuera del tablero, no se lanzaros)
	int i = 0;
	for (i = 0; i < CANT_ZOMBIS; i++) {
		posicion_jugadores_rojos[i][0] = -1;
		posicion_jugadores_rojos[i][1] = -1;
		posicion_jugadores_azules[i][0] = -1;
		posicion_jugadores_azules[i][1] = -1;
		tipo_zombi_rojos[i] = 0;
		tipo_zombi_azules[i] = 0;
	} 
	posicion_zombi_a_lanzar_rojo = 0;
	posicion_zombi_a_lanzar_azul = 0;
	pintar_posicion_zombi_jugador_rojo(0, TIPO_MAGO);
	pintar_posicion_zombi_jugador_azul(0, TIPO_MAGO);
	
}

// devuelve la coordenada x del zombie rojo
int dame_posicion_x_rojo(int nroZombie) {
	return posicion_jugadores_rojos[nroZombie][0]-1;
}

// devuleve la coordenada y del zombie rojo
int dame_posicion_y_rojo(int nroZombie) {
	return posicion_jugadores_rojos[nroZombie][1]-1;
}

// devuelve la coordenada x del zombie azul
int dame_posicion_x_azul(int nroZombie) {
	return posicion_jugadores_azules[nroZombie][0]-1;
}

// devuleve la coordenada y del zombie azul
int dame_posicion_y_azul(int nroZombie) {
	return posicion_jugadores_azules[nroZombie][1]-1;
}

// tipo de zombie rojo
int dame_tipo_zombi_rojo(int nroZombie) {
	return tipo_zombi_rojos[nroZombie];
}

// tipo de zombie azul
int dame_tipo_zombi_azul(int nroZombie) {
	return tipo_zombi_azules[nroZombie];
}


